Executor 框架 - 线程池
概念
线程池(Thread Pool)是一种线程使用模式。当线程使用不当,创建过多时会带来调度的开销,进而影响缓存局部性和整体性能。而线程池维护着若干个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。
重要成员
在 Java 中,线程池一般都是通过 ThreadPoolExecutor 来构建的,下面将介绍 ThreadPoolExecutor 的构造函数部分。
1 | public ThreadPoolExecutor(int corePoolSize, |
参数 | 作用 |
---|---|
corePoolSize | 线程池中所保存的核心线程数。线程池启动时默认是空的,只有任务来临时才会创建线程以处理请求。在 corePoolSize 范围内已创建的线程即使处于空闲状态,除非设置了 allowCoreThreadTimeOut,否则不会被销毁 |
maximumPoolSize | 线程池允许创建的最大线程数。 |
keepAliveTime | 当线程池中的线程超过了 corePoolSize 的范围时,终止过多的空闲线程的时间 |
unit | keepAliveTime 的时间单位 |
workQueue | 用于容纳所有待执行的任务的工作队列。该工作队列只能够容纳实通过 execute() 方法提交的实现 Runnable 接口的任务 |
threadFactory | 用于 executor 如何创建一个线程(一般使用默认线程工厂DefaultThreadFactory) |
handler | 当线程池与工作队列的容量已满时,任务提交被拒绝时所采取的拒绝策略。 |
工作流程
以下流程为向线程池中正常提交任务时的基本流程:
- 线程池判断核心线程池(corePoolSize)里的线程是否都在执行任务,如果不是,则创建一个新的工作线程(或复用一个工作线程)来执行任务。如果核心线程池里的线程都在执行任务,则执行第二步。
- 线程池判断工作队列(workQueue)是否已经满了。如果工作队列没有满,则将新提交的任务存储到工作队列中,等待被调度执行。如果工作队列已满,则执行第三步。
- 线程池判断线程池的线程是否已经满了(maximumPoolSize)。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则根据线程池的拒绝策略来处理该任务。
以上两图均来自于这篇博客Java线程池(ThreadPoolExecutor)原理分析与使用 - 孙_悟__空
拒绝策略
线程池中已经定义了四种任务提交的拒绝策略(以下策略我都贴出源码部分,怕翻译有问题):
- AbortPolicy :不执行任务,并直接抛出一个运行时异常。
1 | A handler for rejected tasks that throws a RejectedExecutionException |
- DiscardPolicy :(silently)直接抛弃任务,其内部实现是一个空方法。
1 | A handler for rejected tasks that silently discards the rejected task. |
- DiscardOldestPolicy : 从工作队列中抛弃最老的未处理的任务,并尝试重新执行该任务。
1 | A handler for rejected tasks that discards the oldest unhandled request |
- CallerRunsPolicy : 线程池直接创建一个 calling 线程来执行任务。
1 | A handler for rejected tasks that runs the rejected task directly in the |
参考资料